﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DTO;

namespace RectanglePacker
{
    public class TreeNode
    {

        public TreeNode()
        {
            m_pLeaf1 = null;
            m_pLeaf2 = null;
        }
        public TreeNode(int x, int y, int width, int height)
        {
            m_x = x;
            m_y = y;
            m_width = width;
            m_height = height;
            m_pLeaf1 = null;
            m_pLeaf2 = null;
        }
        ~TreeNode() { }
        public void Set(int x, int y, int width, int height)
        {
            m_x = x;
            m_y = y;
            m_width = width;
            m_height = height;
            m_pLeaf1 = null;
            m_pLeaf2 = null;
        }
        public bool Add(FModule pFTBitmapChar)
        {
            if (pFTBitmapChar.Module.W == 0 || pFTBitmapChar.Module.H == 0) return true;
            if (IsEmpty())
            {
                if (Fits(pFTBitmapChar))
                {
                    CreateBranches(pFTBitmapChar);
                    pFTBitmapChar.Ox = m_x;
                    pFTBitmapChar.Oy = m_y;
                    return true;
                }
                return false;
            }
            if (m_pLeaf1.Add(pFTBitmapChar))
            {
                return true;
            }
            if (m_pLeaf2.Add(pFTBitmapChar))
            {
                return true;
            }
            return false;
        }
        public bool IsEmpty()
        {
            return m_pLeaf1 == null && m_pLeaf2 == null;
        }


        private void CreateBranches(FModule pFTBitmapChar) 
        {
            int dx = m_width - pFTBitmapChar.Module.W;
            int dy = m_height - pFTBitmapChar.Module.H;
            // we split to give one very small leaf and one very big one
            // because it allows more efficent use of space
            // if you don't do this, the bottom right corner never gets used
            if (dx < dy)
            {
                //	split so the top is cut in half and the rest is one big rect below
                m_pLeaf1 = new TreeNode();
                m_pLeaf1.Set(m_x + pFTBitmapChar.Module.W, m_y,
                        m_width - pFTBitmapChar.Module.W,
                        pFTBitmapChar.Module.H);
                m_pLeaf2 = new TreeNode();
                m_pLeaf2.Set(m_x, m_y + pFTBitmapChar.Module.H,
                        m_width, m_height - pFTBitmapChar.Module.H);
            }
            else
            {
                //	m_pLeaf1 = left (cut in half)
                m_pLeaf1 = new TreeNode();
                m_pLeaf1.Set(m_x, m_y + pFTBitmapChar.Module.H,
                        pFTBitmapChar.Module.W, m_height - pFTBitmapChar.Module.H);
                // m_pLeaf2 = right (not cut)
                m_pLeaf2 = new TreeNode();
                m_pLeaf2.Set(m_x + pFTBitmapChar.Module.W, m_y,
                        m_width - pFTBitmapChar.Module.W, m_height);
            }
        }
        private bool Fits(FModule pFTBitmapChar)
        {
            return pFTBitmapChar.Module.W <= m_width && pFTBitmapChar.Module.H <= m_height;
        }
        private int m_x;
        private int m_y;
        private int m_width;
        private int m_height;
        private TreeNode m_pLeaf1;
        private TreeNode m_pLeaf2;

    }
}
